{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Making Pseudo-Quantum Computer Music in Windows\n",
    "## 1.0 Basic Superposition \n",
    "\n",
    "### Contributor: Alexis Kirke\n",
    "\n",
    "A step by step tutorial on making pseudo-quantum computer music in Python on a Windows OS.\n",
    "\n",
    "Quantum computer music is music generated using quantum computers that takes advantage of the quantum computer speed-up. Pseudo Quantum Computer Music is music generated using quantum processes that doesn't take advantage of the quantum computer speed-up. \n",
    "This tutorial demonstrates how to use quantum processes to create music.\n",
    "\n",
    "Pseudo-Quantum Computer Music, although in itself not more useful than traditional computer music, is a fun and useful way to learn quantum computer programming.\n",
    "\n",
    "The examples given here will use the simulator, as the hardware requires a unique and private key. But they will be created in such a way that they can be run on quantum hardware.\n",
    "\n",
    "First imports are done from the IBM Qiskit library, to enable access to quantum processing. The package winsound is also imported.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 233,
   "metadata": {},
   "outputs": [],
   "source": [
    "import winsound\n",
    "import time\n",
    "import qiskit\n",
    "from qiskit import ClassicalRegister, QuantumRegister\n",
    "from qiskit import QuantumCircuit,  available_backends, execute, register, get_backend\n",
    "from qiskit.backends.jobstatus import JOB_FINAL_STATES\n",
    "from qiskit.tools.visualization import circuit_drawer\n",
    "from qiskit import Aer, IBMQ"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "If you are using Mac or Linux, refer the to relevant tutorial. However winsound is a wonderfully simple package and so will be used here. Now a simple musical tootlkit can will be set up. The user has access to notes in the octave above middle C. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 234,
   "metadata": {
    "scrolled": true
   },
   "outputs": [],
   "source": [
    "C, Db, D, Eb, E, F, Gb, G, Ab, A, Bb, B = 261,277,294,311,330,349,370,392,415,440,466,494"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "This gives the user access to the frequencies of the notes in the octave above middle C. A tune is then defined by making a list of two sub-lists. The first sub-list is set of note name variables, the second sub-list contains the durations in seconds for each pitch."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 235,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[[261, 392, 349, 330, 294, 261, 261], [1, 1, 0.5, 0.5, 0.5, 1, 1]], [[330, 330, 349, 392, 392, 349, 330], [0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5]]]\n"
     ]
    }
   ],
   "source": [
    "tunes = [[[C,G,F,E,D,C,C],[1,1,0.5,0.5,0.5,1,1]]]\n",
    "tunes.append([[E,E,F,G,G,F,E],[0.5]*7])\n",
    "print(tunes)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "A simple way to play the tunes is to use the Beep function available on Windows."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 236,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Playing tune...\n",
      "Playing tune...\n"
     ]
    }
   ],
   "source": [
    "def play_tune(tune):    \n",
    "    print(\"Playing tune...\")\n",
    "    for idx,pitch in enumerate(tune[0]):        \n",
    "        duration_milliseconds = int(tune[1][idx]*1000)\n",
    "        winsound.Beep(pitch,duration_milliseconds)       \n",
    "\n",
    "play_tune(tunes[0])\n",
    "play_tune(tunes[1])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The first process that will be used to make quantum music is superposition. The two tunes will be put into an equal superposition using a quantum computer. Before doing this, the quantum circuit must be prepared. Each note in the tune will be given one line or \"wire\" in the quantum circuit. \n",
    "\n",
    "However for each quantum line, a classical line is also needed. This is because a quantum value cannot be read off. It must first be observed in such a way as to make the superposition collapse, to create a single classical value."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 237,
   "metadata": {},
   "outputs": [],
   "source": [
    "tune_len = len(tunes[0][0])\n",
    "q = QuantumRegister(tune_len)\n",
    "c = ClassicalRegister(tune_len)\n",
    "qc = QuantumCircuit(q,c)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The superposition circuit is created using an Hadamard H gate - hence the qc.h commands below. Every note in the tune is represented by a single H gate. An H-gate creates a superposition of 0 and 1 - the two indices for the `tunes` list. The 0 represents the first tune `tunes[0]` and the the 1 the second tune `tunes[1]`. \n",
    "\n",
    "The qc.measure command observes a quantum state - in a superposition of 0 and 1 - and sends the result to a classical register. The result will be 0 or 1 with a 50 / 50 chance."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 238,
   "metadata": {},
   "outputs": [],
   "source": [
    "for reg in range(0,len(tunes[0][0])):\n",
    "        qc.h(q[reg])        \n",
    "        qc.measure(q[reg],c[reg])\n",
    "diagram = circuit_drawer(qc)\n",
    "diagram.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "To run the quantum circuit the Aer simulator is used. The execute command runs the circuit above on the IBM quantum simulator. The results is turned into a list, which represents the values of the six classical c registers . The list has to be reversed, as Aer returns it in a format which is backwards for our purposes. \n",
    "\n",
    "Thus the ouput of `collapse_tune_superposition()` is the collapsed tunes index superposition, going from note 1 up to note 7."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 239,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Collapsed tune index superposition =  1111101\n"
     ]
    }
   ],
   "source": [
    "def make_tune_superposition():\n",
    "    quantum_backend = Aer.get_backend('qasm_simulator')\n",
    "    circuit_result = execute(qc, backend, shots=1)\n",
    "    tune_indices = list(circuit_result.result().get_counts(qc))[0]   \n",
    "    return(tune_indices[::-1])\n",
    "print(\"Collapsed tune index superposition = \",make_tune_superposition())"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "To each of these three back into tunes, smiply for from left to right and read-off the tune index - 0 for the note from tunes[0] and 1 for the note from tunes[1]. The following function reads off from the two tunes, based on which tune is selecting after the superposition collapse."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 240,
   "metadata": {},
   "outputs": [],
   "source": [
    "def convert_to_tune(collapse, tunes):\n",
    "    collapsed_tune = [[],[]]\n",
    "    for idx,tune_index in enumerate(collapse):\n",
    "        collapsed_tune[0].append(tunes[int(tune_index)][0][idx])\n",
    "        collapsed_tune[1].append(tunes[int(tune_index)][1][idx])\n",
    "    return(collapsed_tune)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The use of these functions can now be demonstrated. First the tunes are put into superposition and collapsed. The results of this collapses give a list of indices for tune 0 or tune 1. The two original tunes are printed out for comparison. The new tune is created by converting the list of tune indices using the pitches and durations from the original tunes.\n",
    "\n",
    "Finally the result of superposing the two tunes is then printed, and played."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 241,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "tune indices =  1000000\n",
      "tunes[0]  [[261, 392, 349, 330, 294, 261, 261], [1, 1, 0.5, 0.5, 0.5, 1, 1]]\n",
      "tunes[1]  [[330, 330, 349, 392, 392, 349, 330], [0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5]]\n",
      "Collapsed tune superposition = [[330, 392, 349, 330, 294, 261, 261], [0.5, 1, 0.5, 0.5, 0.5, 1, 1]]\n",
      "Playing tune...\n"
     ]
    }
   ],
   "source": [
    "collapse = make_tune_superposition()\n",
    "print(\"tune indices = \",collapse)\n",
    "print(\"tunes[0] \",tunes[0])\n",
    "print(\"tunes[1] \",tunes[1])\n",
    "new_tune = convert_to_tune(collapse, tunes)\n",
    "print(\"Collapsed tune superposition =\", new_tune)\n",
    "play_tune(new_tune)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "It can be heard that the tune is a combination of the two original tunes."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "A key point to understand from this, is that within the quantum circuit, the tune is neither tune 0 nor tune 1. It is a combination of the two. But this combination can never be observed directly. The superposition of the two tunes can be represented mathematically as a tensor product of the two tune's indices:\n",
    "\n",
    "$$ T = \\frac{\\left|0\\right\\rangle+\\left|1\\right\\rangle}{\\sqrt{2}}\\otimes\\frac{\\left|0\\right\\rangle+\\left|1\\right\\rangle}{\\sqrt{2}}\\otimes\\frac{\\left|0\\right\\rangle+\\left|1\\right\\rangle}{\\sqrt{2}}\\otimes\\frac{\\left|0\\right\\rangle+\\left|1\\right\\rangle}{\\sqrt{2}}\\otimes\\frac{\\left|0\\right\\rangle+\\left|1\\right\\rangle}{\\sqrt{2}}\\otimes\\frac{\\left|0\\right\\rangle+\\left|1\\right\\rangle}{\\sqrt{2}}\\otimes\\frac{\\left|0\\right\\rangle+\\left|1\\right\\rangle}{\\sqrt{2}}$$"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "keywords = {'Topics': ['Creative','Music'], 'Commands': ['`h`']}"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.0"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
